package de.jmda.mview.typeshape;

import java.awt.Component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.lang.model.element.Element;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;


public class ElementLabelListModel<T extends Element>
    extends DefaultListModel implements ListCellRenderer
{
  private static final long serialVersionUID = 1L;

  private ElementLabel<T>[] elementLabels;
	private DisplayOptionsModelUtil displayOptionsModelUtil;
	
	public ElementLabelListModel(
			Collection<T> elements,
			DisplayOptionsModelUtil displayOptionsModelUtil)
	{
		elementLabels = new ElementLabel[elements.size()];
		this.displayOptionsModelUtil = displayOptionsModelUtil;
		
		// make a list from the collection to be able to sort elements
		List<T> elementList = new ArrayList<T>(elements);

		Collections.sort
		(
				elementList,
				new Comparator<T>()
				{
					@Override
					public int compare(T o1, T o2)
					{
						return
								o1.getSimpleName().toString().compareTo(
								o2.getSimpleName().toString());
					}
				}
		);
		
		// create element labels and find max icon width of element labels
		int i = 0;
		
		int maxIconWidth = 0;
		
		for (T element : elementList)
		{
			elementLabels[i] =
					new ElementLabel<T>(element, displayOptionsModelUtil);

			int iconWidth = elementLabels[i].getIcon().getIconWidth();

			if (iconWidth > maxIconWidth)
			{
				maxIconWidth = iconWidth;
			}

			i++;
		}
		
		for (ElementLabel<T> elementLabel : elementLabels)
		{
			int iconWidth = elementLabel.getIcon().getIconWidth();

			if (iconWidth < maxIconWidth)
			{
				// increase icon text gap by difference between max and actual icon
				// width
				elementLabel.setIconTextGap(
						elementLabel.getIconTextGap() + (maxIconWidth - iconWidth));
			}
		}
	}

	@Override
	public int getSize()
	{
		return elementLabels.length;
	}

	@Override
	public ElementLabel<T> getElementAt(int index)
	{
		return elementLabels[index];
	}
	
	@Override
	public Component getListCellRendererComponent(
			JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
	{
		ElementLabel<?> result;
		
		if (false == (value instanceof ElementLabel<?>))
		{
			throw new IllegalArgumentException(
					"unsupported type " + value.getClass() +
					", expected " + ElementLabel.class);
		}
		
		result = (ElementLabel<?>) value;
		
		if (isSelected)
		{
			result.setBackground(list.getSelectionBackground());
			result.setForeground(list.getSelectionForeground());
    }
		else
		{
			result.setBackground(list.getBackground());
			result.setForeground(list.getForeground());
    }
		
    return result;
	}
}